package com.zx.auth.block.config;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

/**
 * <p>
 * JWK (JSON Web Key) 配置类，用于管理JWT签名和验证所需的密钥对
 * 支持从配置中心加载外部密钥对或动态生成密钥对
 * </p>
 *
 * @author zhou xun
 * @since 2025-10-13
 */
@RefreshScope // 支持Nacos的动态刷新功能
@Configuration
public class JwkConfig {
    /**
     * JWT公钥（从配置中心读取，Base64编码的X.509格式）
     */
    @Value("${jwt.key.public-key:}")
    private String jwtPublicKey;

    /**
     * JWT私钥（从配置中心读取，Base64编码的PKCS#8格式）
     */
    @Value("${jwt.key.private-key:}")
    private String jwtPrivateKey;

    /**
     * 生成或加载RSA密钥对(2048位)并注册为Spring Bean
     * 如果配置了外部密钥，则使用外部密钥，否则抛出异常
     *
     * @return RSA密钥对
     */
    @Bean
    public KeyPair rsaKeyPair() {
        // 检查是否配置了外部密钥
        if (jwtPublicKey != null && !jwtPublicKey.trim().isEmpty() &&
                jwtPrivateKey != null && !jwtPrivateKey.trim().isEmpty()) {
            try {
                // 从Base64字符串还原公钥，去掉首尾空格防止配置粘贴错误
                byte[] publicKeyBytes = Base64.getDecoder().decode(jwtPublicKey.trim());
                PublicKey publicKey = KeyFactory.getInstance("RSA")
                        .generatePublic(new X509EncodedKeySpec(publicKeyBytes));

                // 从Base64字符串还原私钥，去掉首尾空格防止配置粘贴错误
                byte[] privateKeyBytes = Base64.getDecoder().decode(jwtPrivateKey.trim());
                PrivateKey privateKey = KeyFactory.getInstance("RSA")
                        .generatePrivate(new PKCS8EncodedKeySpec(privateKeyBytes));

                return new KeyPair(publicKey, privateKey);
            } catch (Exception ex) {
                throw new IllegalStateException("加载外部JWT密钥失败", ex);
            }
        }
        // 根据项目规范，必须从配置中心获取密钥对，不支持动态生成
        throw new IllegalStateException("必须在Nacos配置中心配置JWT密钥对。" +
                "不支持动态生成密钥对，因为在多实例部署时会导致密钥不一致。");
    }

}